import 'dart:async';

import 'package:flutter/animation.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import '../../../../lib_baseview/utils/screen_utils.dart';
import '../../../../lib_runtime/logger.dart';
import '../../../m_chatroom.dart';
import '../../config/room_config.dart';

class GiftItemController extends GetxController {
  ///礼物播放状态
  DisplayItemGiftStatus giftStatus = DisplayItemGiftStatus.wait;
  AnimationController? inController; //从发送者出来的动画控制器
  late Animation inTranslateX;
  late Animation inTranslateY;
  late Animation inScale;
  late Animation inOpacity;

  AnimationController? outController;
  Map<int, Animation> outTranslateX = {};
  Map<int, Animation> outTranslateY = {};
  Map<int, Animation> outScale = {};
  Map<int, Animation> outOpacity = {};

  RootProxyModel get rootModel => RootProxyModel.instance!;
  late double _giftWidth, _giftHeight, _offsetY, _offsetX;

  final DisplayGiftConfig config;
  final TickerProvider tickerProvider;
  final ValueChanged<DisplayGiftConfig>? completeCallback;

  GiftItemController(this.config, this.tickerProvider, {this.completeCallback});

  // GlobalKey<PAGViewState> pagKey = GlobalKey<PAGViewState>();
  Timer? _timer;
  bool get _specialGift => config.giftId >= 1 && config.giftId <= 6;
  double get giftSize => _giftWidth;

  bool hasCallBack = false;

  @override
  void onInit() {
    super.onInit();
    _initSizes();
    if (config.showAnimation) {
      _initIn();
      _initOut();
    }
    RLog.d('GiftItemController:onInit');
    _timer = Timer(const Duration(seconds: 20), () {
      RLog.d('GiftItemController:delayed');
      _callBackIfNeed();
    });
  }

  @override
  void onReady() {
    super.onReady();
    _playInAnimationIfNeed();
  }

  @override
  void onClose() {
    RLog.d('GiftItemController:onClose');
    if (inController != null) {
      inController?.removeStatusListener(_onInStatus);
      inController?.dispose();
      inController = null;
    }
    if (outController != null) {
      outController?.removeStatusListener(_onOutStatus);
      outController?.dispose();
      outController = null;
    }
    _timer?.cancel();
    _callBackIfNeed();
    super.onClose();
  }

  _callBackIfNeed() {
    RLog.d('GiftItemController:callBack');
    if (!hasCallBack) {
      completeCallback?.call(config);
      hasCallBack = true;
    }
  }

  void _initSizes() {
    double size = ScreenUtils.ins.screenWidth / 2.0;
    RLog.d('_initSizes:${config.giftId}  $size');
    _giftWidth = size;
    _giftHeight = size;
    _offsetX = (ScreenUtils.ins.screenWidth - _giftWidth) / 2.0;
    _offsetY = (ScreenUtils.ins.screenHeight - _giftHeight) / 2.0;
  }

  ///初始化进入动画
  _initIn() {
    // PositionOffset inOffset = rootModel.getPointByUid(config.uid);
    inController = AnimationController(
      duration: const Duration(milliseconds: 1500),
      vsync: tickerProvider,
    );
    inController?.addStatusListener(_onInStatus);
    const double stayThreshold = 0.85;
    inController?.addListener(() {
      double value = inController?.value ?? 0;
      //进场动画快要结束的时候，礼物动画开始展示第一帧，这样会有重叠时间，避免过渡时画面闪烁
      if (value > stayThreshold) {
        if (giftStatus == DisplayItemGiftStatus.inAni) {
          giftStatus = DisplayItemGiftStatus.willAni;
        }
        update();
      }
    });

    Curve stayEndCurve = const StayEndCurve(stayThreshold);
    // inTranslateX = Tween(
    //   begin: inOffset.offset.dx,
    //   end: _offsetX,
    // ).animate(
    //   CurvedAnimation(
    //     parent: inController!,
    //     curve: Interval(
    //       0.5,
    //       1.0,
    //       curve: stayEndCurve,
    //     ),
    //   ),
    // );
    // inTranslateY = Tween(
    //   begin: inOffset.offset.dy,
    //   end: _offsetY,
    // ).animate(
    //   CurvedAnimation(
    //     parent: inController!,
    //     curve: Interval(
    //       0.5,
    //       1.0,
    //       curve: stayEndCurve,
    //     ),
    //   ),
    // );
    // inScale = Tween(
    //   begin: 1.0,
    //   end: _giftWidth / inOffset.size.width,
    // ).animate(
    //   CurvedAnimation(
    //     parent: inController!,
    //     curve: Interval(
    //       0.5,
    //       1.0,
    //       curve: stayEndCurve,
    //     ),
    //   ),
    // );
    // inOpacity = Tween(
    //   begin: 0.0,
    //   end: 1.0,
    // ).animate(
    //   CurvedAnimation(
    //     parent: inController!,
    //     curve: const Interval(
    //       0.0,
    //       0.5,
    //       curve: Curves.easeOut,
    //     ),
    //   ),
    // );
  }

  _onInStatus(AnimationStatus status) {
    RLog.d('GiftItemController:_onInStatus:$status');
    if (status == AnimationStatus.completed) {
      giftStatus = DisplayItemGiftStatus.ani;
    }
    update();
  }

  ///初始化飞出动画
  _initOut() {
    outController = AnimationController(
      duration: const Duration(milliseconds: 1500),
      vsync: tickerProvider,
    );
    outController?.addStatusListener(_onOutStatus);
    // config.uidList?.forEach((int uid) {
    //   // PositionOffset offset = rootModel.getPointByUid(uid);
    //   outTranslateX[uid] = Tween(
    //           begin: 0.0,
    //           end: -ScreenUtils.ins.screenWidth / 2.0 +
    //               offset.offset.dx +
    //               offset.size.width / 2.0)
    //       .animate(
    //     CurvedAnimation(
    //       parent: outController!,
    //       curve: const Interval(
    //         0.0,
    //         0.4,
    //         curve: Curves.linear,
    //       ),
    //     ),
    //   );
    //   outTranslateY[uid] = Tween(
    //           begin: 0.0,
    //           end: -ScreenUtils.ins.screenHeight / 2.0 +
    //               offset.offset.dy +
    //               offset.size.height / 2.0)
    //       .animate(
    //     CurvedAnimation(
    //       parent: outController!,
    //       curve: const Interval(
    //         0.0,
    //         0.4,
    //         curve: Curves.linear,
    //       ),
    //     ),
    //   );
    //   outScale[uid] = Tween(
    //     begin: 1.0,
    //     end: offset.size.width / _giftWidth,
    //   ).animate(
    //     CurvedAnimation(
    //       parent: outController!,
    //       curve: const Interval(
    //         0.0,
    //         0.4,
    //         curve: Curves.linear,
    //       ),
    //     ),
    //   );
    //   outOpacity[uid] = Tween(
    //     begin: 1.0,
    //     end: 0.0,
    //   ).animate(
    //     CurvedAnimation(
    //       parent: outController!,
    //       curve: const Interval(
    //         0.4,
    //         1.0,
    //         curve: Curves.decelerate,
    //       ),
    //     ),
    //   );
    // });
  }

  _onOutStatus(AnimationStatus status) async {
    RLog.d('GiftItemController:_onOutStatus:$status');
    if (status == AnimationStatus.completed) {
      _callBackIfNeed();
    }
  }

  _playInAnimationIfNeed() {
    RLog.d('GiftItemController:_playInAnimationIfNeed:${config.showAnimation}');
    if (config.showAnimation && inController != null) {
      giftStatus = DisplayItemGiftStatus.inAni;
      inController?.reset();
      inController?.forward(from: 0.0);
    } else {
      giftStatus = DisplayItemGiftStatus.ani;
    }
    update();
  }

  startPlayPag() async {
    RLog.d('GiftItemController:startPlayPag');
    // pagKey.currentState?.start();
  }

  /// pag动画播放完成回调
  onPagAnimEnd() {
    RLog.d('GiftItemController:startPlayPagEnd');
    if (config.showAnimation && outController != null) {
      giftStatus = DisplayItemGiftStatus.outAni;
      update();
      outController?.reset();
      outController?.forward();
    } else {
      _callBackIfNeed();
    }
  }
}

class StayEndCurve extends Curve {
  final double threshold;

  const StayEndCurve(this.threshold);

  @override
  double transform(double t) {
    if (t <= threshold) {
      return 1.0 / threshold * t;
    }
    return 1.0;
  }
}

class StayBeginCurve extends Curve {
  final double threshold;

  const StayBeginCurve(this.threshold);

  @override
  double transform(double t) {
    if (t >= threshold) {
      double a = 1 / (1 - threshold);
      double b = 1 - a;
      return a * t + b;
    }
    return 0.0;
  }
}
